using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint.StsAdmin;
using System.Collections.Specialized;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;

namespace DD.SharePoint.STSADM.Extensions
{
    public class ListManagementCommand : ISPStsadmCommand
    {
        #region ISPStsadmCommand Members

        public string GetHelpMessage(string command)
        {
            command = command.ToLowerInvariant();

            switch (command)
            {
                case "emptylist":
                    return "-url <Full url to a site in SharePoint>\n" +
                        "        -list <List Name>\n";
                case "setfieldproperties":
                    return "-url <Full url to a site in SharePoint>\n" +
                        "        -list <List Name>\n" +
                        "        -field <Field Name>\n" +
                        "        [-hide]\n" +
                        "        [-peoplefieldgroupfilter] <Group Name>\n";
                case "relinkinfopathforms":
                    return "-url <Full url to a site in SharePoint>\n" +
                        "        -list <List Name>\n";
                default:
                    throw new InvalidOperationException();
            }
        }

        public int Run(string command, System.Collections.Specialized.StringDictionary keyValues, out string output)
        {
            command = command.ToLowerInvariant();

            switch (command)
            {
                case "emptylist":
                    return EmptyList(keyValues, out output);
                case "setfieldproperties":
                    return SetFieldProperties(keyValues, out output);
                case "relinkinfopathforms":
                    return RelinkInfoPathForms(keyValues, out output);
                case "enumfields":
                    return EnumFields(keyValues, out output);
                default:
                    throw new InvalidOperationException();
            }
        }

        private int RelinkInfoPathForms(StringDictionary keyValues, out string output)
        {

            if (!keyValues.ContainsKey("url"))
            {
                throw new InvalidOperationException("The url parameter was not specified");
            }

            if (!keyValues.ContainsKey("list"))
            {
                throw new InvalidOperationException("The list parameter was not specified");
            }

            StringBuilder sb = new StringBuilder();

            String url = keyValues["url"];
            string listname = keyValues["list"];

            SPWeb web = null;

            try
            {
                web = new SPSite(url).OpenWeb();
            }
            catch (Exception)
            {
                throw new InvalidOperationException("Error retrieving url '" + url + "'.");
            }

            SPList list = null;
            SPDocumentLibrary docLibrary = null;

            try
            {
                list = web.Lists[listname];
                docLibrary = (SPDocumentLibrary)list;
            }
            catch (Exception)
            {
                throw new InvalidOperationException("List '" + listname + "' does not exist at this site level or is not a document library.");
            }

            try
            {
                string templateUrl = SPHttpUtility.UrlPathEncode(web.Url + "/" + docLibrary.DocumentTemplateUrl, true);

                foreach (SPListItem item in docLibrary.Items)
                {
                    SPFieldCollection fields = item.Fields;
                    foreach (SPField field in fields)
                    {
                        if (field.Type != SPFieldType.Computed && field.Type != SPFieldType.Invalid && !field.ReadOnlyField)
                        {
                            item[field.InternalName] = item[field.InternalName];
                        }
                    }


                    SPContentType contentType = list.ContentTypes[(SPContentTypeId)item["ContentTypeId"]];
                    if (contentType != null)
                    {
                        if (contentType.DocumentTemplate.ToLower().StartsWith("http://") ||
                                contentType.DocumentTemplate.ToLower().StartsWith("https://"))
                        {
                            item["TemplateUrl"] = SPHttpUtility.UrlPathEncode(contentType.DocumentTemplate, true);
                        }
                        else if (contentType.DocumentTemplate.StartsWith("/"))
                        {
                            item["TemplateUrl"] = SPHttpUtility.UrlPathEncode(web.Site.MakeFullUrl(contentType.DocumentTemplate), true);
                        }
                        else
                        {
                            item["TemplateUrl"] = SPHttpUtility.UrlPathEncode(web.Url + "/" + list.RootFolder + "/" + contentType.DocumentTemplate, true);
                        }
                    }
                    else
                    {
                        item["TemplateUrl"] = templateUrl;
                    }

                    item.Update();
                    sb.Append("Relinking file " + item.Title);
                }

                sb.Append("Operation successfully completed");
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException("Error occured: " + ex.Message + "\n\n" + ex.StackTrace);
            }

            output = sb.ToString();

            return 0;
        }

        private int EnumFields(StringDictionary keyValues, out string output)
        {

            if (!keyValues.ContainsKey("url"))
            {
                throw new InvalidOperationException("The url parameter was not specified");
            }

            if (!keyValues.ContainsKey("list"))
            {
                throw new InvalidOperationException("The list parameter was not specified");
            }

            StringBuilder sb = new StringBuilder();

            String url = keyValues["url"];
            string listname = keyValues["list"];

            SPWeb web = null;

            try
            {
                web = new SPSite(url).OpenWeb();
            }
            catch (Exception)
            {
                throw new InvalidOperationException("Error retrieving url '" + url + "'.");
            }

            SPList list = null;

            try
            {
                list = web.Lists[listname];
            }
            catch (Exception)
            {
                throw new InvalidOperationException("List '" + listname + "' does not exist at this site level.");
            }

            try
            {
                foreach (SPField field in list.Fields)
                {
                    sb.Append(field.StaticName + ": " + field.InternalName);
                }
            }
            catch (Exception)
            {
                throw new InvalidOperationException("Field '' does not exist at this site level.");
            }

            output = sb.ToString();

            return 0;
        }

        private int SetFieldProperties(StringDictionary keyValues, out string output)
        {
            if (!keyValues.ContainsKey("url"))
            {
                throw new InvalidOperationException("The url parameter was not specified");
            }

            if (!keyValues.ContainsKey("list"))
            {
                throw new InvalidOperationException("The list parameter was not specified");
            }

            if (!keyValues.ContainsKey("field"))
            {
                throw new InvalidOperationException("The field parameter was not specified");
            }

            StringBuilder sb = new StringBuilder();

            String url = keyValues["url"];
            string listname = keyValues["list"];
            string fieldname = keyValues["field"];

            SPWeb web = null;

            try
            {
                web = new SPSite(url).OpenWeb();
            }
            catch (Exception)
            {
                throw new InvalidOperationException("Error retrieving url '" + url + "'.");
            }

            SPList list = null;

            try
            {
                list = web.Lists[listname];
            }
            catch (Exception)
            {
                throw new InvalidOperationException("List '" + listname + "' does not exist at this site level.");
            }

            SPField field = null;
            try
            {
                field = list.Fields.GetField(fieldname);
            }
            catch (Exception)
            {
                throw new InvalidOperationException("Field '" + fieldname + "' does not exist at this site level.");
            }

            try
            {
                if (keyValues.ContainsKey("hide"))
                {
                    field.ShowInDisplayForm = false;
                    field.ShowInEditForm = false;
                    field.ShowInNewForm = false;
                    field.ShowInVersionHistory = false;
                    field.ShowInViewForms = false;
                    field.Update();

                    sb.Append("Operation successfully completed");
                }

                if (keyValues.ContainsKey("show"))
                {
                    field.ShowInDisplayForm = false;
                    field.ShowInEditForm = false;
                    field.ShowInNewForm = false;
                    field.ShowInVersionHistory = false;
                    field.ShowInViewForms = false;
                    field.Update();

                    sb.Append("Operation successfully completed");
                }
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException("Field cannot be updated: " + ex.Message);
            }

            if (keyValues.ContainsKey("peoplefieldgroupfilter"))
            {
                if (field.Type != SPFieldType.User)
                    throw new InvalidOperationException("Field '" + fieldname + "' is not a People field");

                try
                {
                    SPFieldUser userField = (SPFieldUser)field;
                    userField.SelectionGroup = web.SiteGroups[keyValues["peoplefieldgroupfilter"]].ID;
                    userField.Update();

                    sb.Append("Operation successfully completed");
                }
                catch (Exception)
                {
                    throw new InvalidOperationException("Group '" + keyValues["peoplefieldgroupfilter"] + "' does not exist at this site level.");
                }
            }

            output = sb.ToString();

            return 0;
        }

        private int SetPeopleFieldGroupFilter(StringDictionary keyValues, out string output)
        {
            if (!keyValues.ContainsKey("url"))
            {
                throw new InvalidOperationException("The url parameter was not specified");
            }

            if (!keyValues.ContainsKey("list"))
            {
                throw new InvalidOperationException("The list parameter was not specified");
            }

            if (!keyValues.ContainsKey("field"))
            {
                throw new InvalidOperationException("The field parameter was not specified");
            }

            if (!keyValues.ContainsKey("group"))
            {
                throw new InvalidOperationException("The group parameter was not specified");
            }

            StringBuilder sb = new StringBuilder();

            String url = keyValues["url"];
            string listname = keyValues["list"];
            string fieldname = keyValues["field"];
            string groupname = keyValues["group"];

            SPWeb web = null;

            try
            {
                web = new SPSite(url).OpenWeb();
            }
            catch (Exception)
            {
                throw new InvalidOperationException("Error retrieving url '" + url + "'.");
            }

            SPList list = null;

            try
            {
                list = web.Lists[listname];
            }
            catch (Exception)
            {
                throw new InvalidOperationException("List '" + listname + "' does not exist at this site level.");
            }

            SPField field = null;
            try
            {
                field = list.Fields.GetField(fieldname);
            }
            catch (Exception)
            {
                throw new InvalidOperationException("Field '" + fieldname + "' does not exist at this site level.");
            }

            if (field.Type != SPFieldType.User)
                throw new InvalidOperationException("Field '" + fieldname + "' is not a People field");

            try
            {
                SPFieldUser userField = (SPFieldUser)field;
                userField.SelectionGroup = web.SiteGroups[groupname].ID;
                userField.Update();

                sb.Append("Operation successfully completed");
            }
            catch (Exception)
            {
                throw new InvalidOperationException("Group '" + groupname + "' does not exist at this site level.");
            }

            output = sb.ToString();

            return 0;
        }

        private int EmptyList(StringDictionary keyValues, out string output)
        {
            if (!keyValues.ContainsKey("url"))
            {
                throw new InvalidOperationException("The url parameter was not specified");
            }

            if (!keyValues.ContainsKey("list"))
            {
                throw new InvalidOperationException("The list parameter was not specified");
            }

            StringBuilder sb = new StringBuilder();

            String url = keyValues["url"];
            string listname = keyValues["list"];

            SPWeb web = null;

            try
            {
                web = new SPSite(url).OpenWeb();
            }
            catch (Exception)
            {
                throw new InvalidOperationException("Error retrieving url '" + url + "'.");
            }

            try
            {
                SPListItemCollection items = web.Lists[listname].Items;
                foreach (SPListItem item in items)
                {
                    web.Lists[listname].Items.DeleteItemById(item.ID);
                }

                sb.Append("Operation successfully completed");
            }
            catch (Exception)
            {
                throw new InvalidOperationException("List '" + listname + "' does not exist at this site level.");
            }

            output = sb.ToString();

            return 0;
        }

        #endregion
    }
}
